#include <string.h>
#include <cmath>
#include <iostream> //预处理器指令 a PREPROCESSOR directive
#include <vector>
#include <array>

using namespace std; // 使定义可见   make definitions visible

namespace VECTOR
{
  class Vector
  {
  public:
    enum Mode {RECT,POL}; //状态成员(state member) 描述的是对象所处的状态
    /*
      RECT for rectangular, POL for Polar modes
      RECT表示矩形，POL表示极坐标模式
      标识两种表示法: 
      大小(长度)和方向(角度)    极坐标模式
      分量x和y表示             直角坐标模式 - 矩形
    */

  private:
    double x;   // horizontal(水平) value
    double y;   // vertical(垂直) value
    double mag; // length of vector
    double ang; // direction of vector in degrees 矢量方向（度）

    //一个矢量拥有方向(direction)和大小(magnitude)也称为长度(length)

    Mode mode;  // RECT or POL
    
    // private methods for setting values
    void set_mag();
    void set_ang();
    void set_x();
    void set_y();

  public:
    Vector();
    Vector(double n1, double n2, Mode form = RECT);
    void reset(double n1, double n2, Mode form = RECT);
    ~Vector();

    //函数是在类声明中定义的，因此将自动成为内联函数。
    //const限定符  不会修改对象数据
    double xval() const { return x; }     // report x value
    double yval() const { return y; }     // report y value
    double magval() const { return mag; } // report magnitude
    double angval() const { return ang; } // report angle
    
    void polar_mode();                    // set mode to POL
    void rect_mode();                     // set mode to RECT
    
    // operator overloading
    Vector operator+(const Vector &b) const;
    Vector operator-(const Vector &b) const;
    Vector operator-() const;
    Vector operator*(double n) const;

    // friends
    friend Vector operator*(double n, const Vector &a);
    friend std::ostream &operator<<(std::ostream &os, const Vector &v);
  };

} // end namespace VECTOR



int main()
{
  using namespace VECTOR; 

  Vector tor1 = Vector();
  tor1.reset(30,40);
  cout << tor1;

  Vector shove ;
  shove = Vector(100,300);//create and assign a temporary(临时) object
  //使用构造函数将增加额外的步骤：创建一个临时对象，然后将其赋给shove。

  //诸如2等整数不能隐式地转换为枚举类型
  Vector rector(20.0,30.0,VECTOR::Vector::Mode(2));//typecast

  //time(0)函数返回当前时间，通常为从某一个日期开始的秒数
  cout << (time(0));
}

namespace VECTOR
{
    // compute degrees in one radian
    const double Rad_to_deg = 45.0 / atan(1.0);
    // should be about 57.2957795130823

    // private methods
    // calculates magnitude from x and y
    // 通过x和y计算长度
    void Vector::set_mag()
    {
        mag = sqrt(x * x + y * y);
    }

    void Vector::set_ang()
    {
        if (x == 0.0 && y == 0.0)
            ang = 0.0;
        else
            ang = atan2(y, x);
    }

    // set x from polar coordinate
    void Vector::set_x()
    {
        x = mag * cos(ang);
    }

    // set y from polar coordinate
    void Vector::set_y()
    {
        y = mag * sin(ang);
    }

    // public methods
    Vector::Vector()             // default constructor
    {
        x = y = mag = ang = 0.0;
        mode = RECT;
    }

    // construct vector from rectangular coordinates if form is r
    // (the default) or else from polar coordinates if form is p
    //如果form是r（默认值），则从直角坐标构造向量；如果form是p，则从极坐标构造向量
    Vector::Vector(double n1, double n2, Mode form)
    {
        mode = form;
        if (form == RECT)
         {
             x = n1;
             y = n2;
             set_mag();
             set_ang();
        }
        else if (form == POL)
        {
             mag = n1;
             ang = n2 / Rad_to_deg;
             set_x();
             set_y();
        }
        else
        {
             cout << "Incorrect 3rd argument to Vector() -- ";
             cout << "vector set to 0\n";
             x = y = mag = ang = 0.0;
             mode = RECT;
        }
    }

    // reset vector from rectangular coordinates if form is
    // RECT (the default) or else from polar coordinates if form is POL

    //rectangular coordinates 直角坐标系 
    //如果form是RECT（默认），则从直角坐标重置矢量，如果form是POL，则从极坐标重置矢量
    void Vector:: reset(double n1, double n2, Mode form)
    {
        mode = form;
        if (form == RECT)
         {
             x = n1;
             y = n2;
             set_mag();
             set_ang();
        }
        else if (form == POL)
        {
             mag = n1;
             ang = n2 / Rad_to_deg;
             set_x();
             set_y();
        }
        else
        {
             cout << "Incorrect 3rd argument to Vector() -- ";
             cout << "vector set to 0\n";
             x = y = mag = ang = 0.0;
             mode = RECT;
        }
    }

    Vector::~Vector()    // destructor
    {
    }

    void Vector::polar_mode()    // set to polar mode
    {
        mode = POL;
    }

    void Vector::rect_mode()     // set to rectangular mode
    {
        mode = RECT;
    }

    // operator overloading  - V3
    // add two Vectors
    Vector Vector::operator+(const Vector & b) const
    {
        return Vector(x + b.x, y + b.y);
    }


    /*
      //未设置极坐标 - V1
      Vector Vector::operator+(const Vector& b) const{
        Vector sum;
        sum.x = x + b.x;
        sum.y = y + b.y;
        return sum;//incomplete(不完整) version
      }

      //添加极坐标 - V2
      Vector Vector::operator+(const Vector& b)const{
        Vector sum;
        sum.x = x + b.x;
        sum.y = y + b.y;
        sum.set_ang();
        sum.set_mag();
        return sum;
        //version duplicates needlessly 
        //版本不必要地重复 (和构造函数)
      }
    */

   //-运算符已经有两种含义 减法(二元运算符) 和 负号(一元运算符)

    // subtract Vector b from a
    //隐式矢量参数减去以显式参数传递的矢量，所以应使用x - b.x,而不是b.x - x。
    Vector Vector::operator-(const Vector & b) const
    {
        return Vector(x - b.x, y - b.y);
    }

    // reverse sign of Vector 矢量的逆符号
    Vector Vector::operator-() const
    {
        return Vector(-x, -y);
    }

    // multiply vector by n
    Vector Vector::operator*(double n) const
    {
        return Vector(n * x, n * y);
    }

    // friend methods
    // multiply(乘) n by Vector a
    Vector operator*(double n, const Vector & a)
    {
        return a * n;
    }

    // display rectangular coordinates if mode is RECT,  else display polar coordinates if mode is POL
    // 如果模式为RECT，则显示直角坐标；如果模式为POL，则显示极坐标
    std::ostream & operator<<(std::ostream & os, const Vector & v)
    {
        if (v.mode == Vector::RECT)
             os << "(x,y) = (" << v.x << ", " << v.y << ")";
        else if (v.mode == Vector::POL)
        {
             os << "(m,a) = (" << v.mag << ", "
                 << v.ang * Rad_to_deg << ")";
        }
        else
             os << "Vector object mode is invalid";
        return os; 
    }
}  // end namespace VECTOR















